#include <REGX52.H>

//引脚定义
sbit DS1302_SCLK=P3^6;	//时钟针脚 输入. SCLK 用来同步串行接口上的数据动作.此管脚内部有一个
						//40kΩ(典型值)的下拉电阻连接到地

sbit DS1302_IO=P3^4;	//数据针脚 推挽输出.I/O 管脚是三线接口的双向数据管脚.此管脚内部有
						//一个 40kΩ(典型值)的下拉电阻连接到地

sbit DS1302_CE=P3^5;	//重置位针脚  CE信号在读写时必须保持高电平.此管脚内部有一个 40kΩ(典
						//型值)的下拉电阻连接到地. 注意:先前的数据手册修正把 CE当作 
						//RST. 管脚的功能没有改变.


//寄存器写入地址/指令定义
#define DS1302_YEAR			0x8C	//年
#define DS1302_MONTH		0x88	//月	
#define DS1302_DATE			0x86	//日
#define DS1302_HOUR			0x84	//时
#define DS1302_MINUTE		0x82	//分
#define DS1302_SECOND		0x80	//秒
#define DS1302_WEEK			0x8A	//星期
#define DS1302_WP			0x8E	//写保护位 
									//控制寄存器的位 7是写保护位，前 7位（位 0至位 6）被强制为 0且读取时总是读 0. 在任
									//何对时钟或 RAM的写操作以前，位 7必须为 0.当为高时，写保护位禁止任何寄存器的写操
									//作. 初始加电状态未定义. 因此，在试图写器件之前应该清除 WP位.

//时间数组，索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={24,6,26,18,59,55,3};

/**
 * 函    数：DS1302初始化
 * 参    数：无
 * 返 回 值：无
 */
void DS1302_Init(void)
{
	DS1302_CE=0;	//重置数据引脚，没有读写数据时给低电平
	DS1302_SCLK=0;	//时钟引脚，没有读写操作时给低电平
}

/**
 * 函    数：DS1302写一个字节
 * 参    数：Addr 命令字/DS1302寄存器地址
			 Data 要写入的数据
 * 返 回 值：无
 */
void DS1302_WriteByte(unsigned char Addr,Data)
{
	unsigned char i;
	DS1302_CE=1;//读写数据时都置高电平
	/*在IO上先写入寄存器地址*/
	for(i=0;i<8;i++)
	{
		DS1302_IO=Addr&(0x01<<i);	//地址
		DS1302_SCLK=1;	//高电平
		DS1302_SCLK=0;	//低电平
	}
	for(i=0;i<8;i++)
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;
}
 
/**
 * 函    数：DS1302读一个字节
 * 参    数：Addr 命令字/DS1302寄存器地址
 * 返 回 值：无
 */
unsigned char DS1302_ReadByte(unsigned char Addr)
{
	unsigned char i,Data=0x00;
	Addr|=0x01;		//将指令转换为读指令
	DS1302_CE=1;	//读写数据时都置高电平
	for(i=0;i<8;i++)
	{
		DS1302_IO=Addr&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;	//读取后将IO设置为0，否则读出的数据会出错
	return Data;
}
 
/**
 * 函    数：DS1302设置时间，调用之后，DS1302_Time数组的数字会被设置到DS1302中
 * 参    数：无
 * 返 回 值：无
 */
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_WEEK,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0x80);
}

/**
 * 函    数：DS1302读取时间，调用之后，DS1302中的数据会被读取到DS1302_Time数组中
 * 参    数：无
 * 返 回 值：无
 */
void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_WEEK);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}
